package org.study.enums;

/**
 * 枚举类也可以用来实现状态模式，每个枚举常量代表系统的一种状态，并提供状态相关行为的实现。
 * 参考 https://blog.csdn.net/MeyrlNotFound/article/details/147870300
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2025年07月16日
 */
public class VendingMachineEnumTest {
    public static void main(String[] args) {
        VendingMachine vendingMachine = new VendingMachine();
        vendingMachine.selectItem();
        vendingMachine.insertCoin();
        vendingMachine.dispenseItem();
    }

    public enum VendingMachineState {
        IDLE {
            @Override
            public void insertCoin(VendingMachine machine) {
                System.out.println("硬币已插入");
                machine.setState(HAS_COIN);
            }

            @Override
            public void selectItem(VendingMachine machine) {
                System.out.println("请先插入硬币");
            }

            @Override
            public void dispenseItem(VendingMachine machine) {
                System.out.println("请先选择商品");
            }
        },
        HAS_COIN {
            @Override
            public void insertCoin(VendingMachine machine) {
                System.out.println("已有一枚硬币，不能再插入");
            }

            @Override
            public void selectItem(VendingMachine machine) {
                System.out.println("商品已选择");
                machine.setState(DISPENSING);
            }

            @Override
            public void dispenseItem(VendingMachine machine) {
                System.out.println("请先选择商品");
            }
        },
        DISPENSING {
            @Override
            public void insertCoin(VendingMachine machine) {
                System.out.println("正在分发商品，请等待");
            }

            @Override
            public void selectItem(VendingMachine machine) {
                System.out.println("正在分发商品，请等待");
            }

            @Override
            public void dispenseItem(VendingMachine machine) {
                System.out.println("商品已分发");
                machine.setState(IDLE);
            }
        };

        public abstract void insertCoin(VendingMachine machine);

        public abstract void selectItem(VendingMachine machine);

        public abstract void dispenseItem(VendingMachine machine);
    }

    public static class VendingMachine {
        private VendingMachineState state = VendingMachineState.IDLE;

        public void setState(VendingMachineState state) {
            this.state = state;
        }

        public void insertCoin() {
            state.insertCoin(this);
        }

        public void selectItem() {
            state.selectItem(this);
        }

        public void dispenseItem() {
            state.dispenseItem(this);
        }
    }
}
